package cn.jasonone.jfx.factory;

import cn.hutool.core.lang.Assert;
import cn.jasonone.jfx.bind.DefaultBindProperty;
import javafx.scene.control.Control;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

/**
 * @author xujie
 * @version 1.0
 * @date 2021/12/23 11:26
 */
@Slf4j
@Component("bindPropertyFactory")
public class DefaultBindPropertyFactory implements BindPropertyFactory, InitializingBean {
    @Resource
    private ApplicationContext applicationContext;

    private Map<Class<Control>, DefaultBindProperty> bindPropertyMap = new HashMap<>();

    @Override
    public DefaultBindProperty getDefaultBindProperty(Class<? extends Control> controlClass) {
        if (bindPropertyMap.containsKey(controlClass)) {
            return bindPropertyMap.get(controlClass);
        } else {
            Class<?> superclass = controlClass.getSuperclass();
            if (Control.class.isAssignableFrom(superclass)) {
                DefaultBindProperty bindProperty = getDefaultBindProperty((Class<? extends Control>) superclass);
                if (bindProperty != null) {
                    return bindProperty;
                }
            }
            Class<?>[] interfaces = controlClass.getInterfaces();
            if (interfaces != null) {
                for (Class<?> anInterface : interfaces) {
                    if (Control.class.isAssignableFrom(anInterface)) {
                        DefaultBindProperty bindProperty = getDefaultBindProperty((Class<? extends Control>) anInterface);
                        if (bindProperty != null) {
                            return bindProperty;
                        }
                    }
                }
            }
        }
        return null;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Map<String, DefaultBindProperty> defaultBindPropertyMap = applicationContext.getBeansOfType(DefaultBindProperty.class);
        if (defaultBindPropertyMap != null) {
            defaultBindPropertyMap.values().forEach(bindProperty -> {
                Class<Control> controlClass = null;
                //region 获取DefaultBindProperty接口的泛型类型
                Class<? extends DefaultBindProperty> bindPropertyClass = bindProperty.getClass();
                Type[] genericInterfaces = bindPropertyClass.getGenericInterfaces();
                for (Type genericInterface : genericInterfaces) {
                    if (genericInterface instanceof ParameterizedType) {
                        ParameterizedType pt = (ParameterizedType) genericInterface;
                        if (DefaultBindProperty.class.isAssignableFrom((Class<?>) pt.getRawType())) {
                            controlClass = (Class<Control>) pt.getActualTypeArguments()[0];
                        }
                    }
                }
                //endregion
                Assert.notNull(controlClass, "控件类型不能为null");
                log.debug("注册控件默认值绑定处理器[{}]:{}", controlClass.getName(), bindProperty);
                bindPropertyMap.put(controlClass, bindProperty);
            });
        }
    }
}
